package org.dromara.system.openApi.security;

import cn.dev33.satoken.exception.SaSignException;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.crypto.digest.DigestUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.security.config.ICustomSecurityCheck;
import org.dromara.system.openApi.domain.OpenApiClient;
import org.dromara.system.openApi.service.IOpenApiClientService;
import org.springframework.stereotype.Service;

@Slf4j
@Service("openApi"+ICustomSecurityCheck.BASE_NAME)
public class OpenApiSecurityCheck implements ICustomSecurityCheck {

    @Resource
    private IOpenApiClientService openApiClientService;
    //随机数
    private final String OPEN_API_RANDOM_STR = "randomStr";
    //当前时间
    private final String OPEN_API_cur_Time = "curTime";
    //签名
    private final String OPEN_API_sign = "sign";
    @Override
    public void check() {
        HttpServletRequest request = ServletUtils.getRequest();
        String clientId = request.getHeader(LoginHelper.CLIENT_KEY);
        String randomStr = request.getHeader(OPEN_API_RANDOM_STR);
        String curTime = request.getHeader(OPEN_API_cur_Time);
        String sign = request.getHeader(OPEN_API_sign);
        if(BooleanUtil.isFalse(NumberUtil.isNumber(curTime))){
            log.info("clientId={},randomStr={},curTime={},请求上送的签名sign为{}",clientId,randomStr,curTime,sign);
            SaSignException.throwBy(true,"openApi签名验证失败,curTime错误");
        }
        //根据clientId查询到密钥
        OpenApiClient openApiClient = openApiClientService.queryByClientId(clientId);
        if(null == openApiClient){
            SaSignException.throwBy(true,"openApi签名验证失败,clientId错误");
        }
        //验证签
        String clientSecret = openApiClient.getClientSecret();
        String toMd5str = (clientId+randomStr+curTime+clientSecret).toUpperCase();
        String signCheck= DigestUtil.md5Hex(toMd5str).toUpperCase();
        if(BooleanUtil.isTrue(openApiClient.getCheckSign()) && !signCheck.equals(sign)){
            log.info("clientId={},randomStr={},curTime={},签名前字符为{}，签名signCheck为{}，请求上送的签名sign为{}",clientId,randomStr,curTime,toMd5str,signCheck,sign);
            SaSignException.throwBy(true,"openApi签名验证失败");
        }
        int diffCurTime = openApiClient.getDiffCurTime();
        long nowTime = DateUtil.current();
        long diffTime = Math.abs(nowTime - Long.parseLong(curTime));

        //验证是否在允许的最大时间差内
        if(diffCurTime > 0 && diffTime > diffCurTime*60*1000 ){
            log.info("clientId={},randomStr={},curTime={},签名前字符为{}，签名signCheck为{}，请求上送的签名sign为{}，系统当前时间为{}",clientId,randomStr,curTime,toMd5str,signCheck,sign,nowTime);
            SaSignException.throwBy(true,"openApi签名验证失败,存在较大时间差");
        }

        //验证接口是否已授权

    }
}
